package com.haohan.cloud.scm.supply.core.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.haohan.cloud.scm.api.constant.enums.common.UseStatusEnum;
import com.haohan.cloud.scm.api.constant.enums.supply.SupplyRelationTypeEnum;
import com.haohan.cloud.scm.api.goods.dto.GoodsExtDTO;
import com.haohan.cloud.scm.api.goods.dto.GoodsModelDTO;
import com.haohan.cloud.scm.api.goods.req.GoodsFeignReq;
import com.haohan.cloud.scm.api.goods.req.GoodsModelFeignReq;
import com.haohan.cloud.scm.api.goods.vo.GoodsVO;
import com.haohan.cloud.scm.api.manage.entity.Merchant;
import com.haohan.cloud.scm.api.manage.entity.Shop;
import com.haohan.cloud.scm.api.supply.dto.SupplyGoodsDTO;
import com.haohan.cloud.scm.api.supply.dto.SupplySqlDTO;
import com.haohan.cloud.scm.api.supply.entity.SupplierGoods;
import com.haohan.cloud.scm.api.supply.req.goods.SupplyGoodsEditReq;
import com.haohan.cloud.scm.api.supply.req.goods.SupplyGoodsPlatformSalesReq;
import com.haohan.cloud.scm.api.supply.req.goods.SupplyGoodsReq;
import com.haohan.cloud.scm.api.supply.trans.SupplyGoodsTrans;
import com.haohan.cloud.scm.api.supply.vo.*;
import com.haohan.cloud.scm.common.tools.exception.ErrorDataException;
import com.haohan.cloud.scm.supply.core.ScmSupplierCoreService;
import com.haohan.cloud.scm.supply.core.ScmSupplyGoodsCoreService;
import com.haohan.cloud.scm.supply.service.SupplierGoodsService;
import com.haohan.cloud.scm.supply.utils.ScmSupplyUtils;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author dy
 * @date 2020/4/17
 * 传入supplierId 按供应商查询
 * 传入shopId 按对应供应商商家店铺查询
 */
@Service
@AllArgsConstructor
public class ScmSupplyGoodsCoreServiceImpl implements ScmSupplyGoodsCoreService {

    private final ScmSupplierCoreService supplierCoreService;
    private final SupplierGoodsService supplierGoodsService;
    private final ScmSupplyUtils scmSupplyUtils;

    /**
     * 供应商及其商家店铺验证
     *
     * @param supplierId
     * @param shopId
     * @return shopId merchantId
     */
    private SupplierMerchantInfoVO checkSupplier(String supplierId, String shopId) {
        SupplierMerchantInfoVO result;
        if (StrUtil.isNotBlank(shopId)) {
            result = new SupplierMerchantInfoVO();
            Shop shop = scmSupplyUtils.fetchShopById(shopId);
            result.setShopId(shopId);
            result.setMerchantId(shop.getMerchantId());
            return result;
        }
        if (StrUtil.isBlank(supplierId)) {
            throw new ErrorDataException("缺少参数supplierId或shopId");
        }
        return supplierCoreService.fetchMerchantInfo(supplierId);
    }

    /**
     * 查询供应商的商品列表 已关联平台的商品标记
     *
     * @param page
     * @param req
     * @return
     */
    @Override
    public IPage<SupplyGoodsVO> findPage(Page page, SupplyGoodsReq req) {
        SupplierMerchantInfoVO merchantShop = checkSupplier(req.getSupplierId(), req.getShopId());
        // 查询商品 shopId
        GoodsFeignReq feignReq = req.tranTo();
        feignReq.setPage(page);
        IPage<GoodsExtDTO> goodsPage = scmSupplyUtils.fetchGoodsPage(feignReq);
        IPage<SupplyGoodsVO> result = new Page<>(goodsPage.getCurrent(), goodsPage.getSize(), goodsPage.getTotal());
        if (CollUtil.isNotEmpty(goodsPage.getRecords())) {
            // 关联商品处理
            int size = Math.max(16, goodsPage.getRecords().size() * 4 / 3 + 1);
            Map<String, SupplyGoodsVO> goodsMap = new HashMap<>(size);
            result.setRecords(goodsPage.getRecords().stream()
                    .map(item -> {
                        SupplyGoodsVO goodsVO = new SupplyGoodsVO(item);
                        goodsMap.put(goodsVO.getGoodsId(), goodsVO);
                        return goodsVO;
                    }).collect(Collectors.toList())
            );
            List<SupplierGoods> list = findEnableListBySupply(merchantShop.getMerchantId(), goodsMap.keySet(), null);
            list.forEach(item -> {
                SupplyGoodsVO goodsVO = goodsMap.get(item.getSupplyGoodsId());
                if (null == goodsVO) {
                    return;
                }
                SupplyRelationTypeEnum type = SupplyRelationTypeEnum.supplier;
                if (StrUtil.isEmpty(item.getSupplierId())) {
                    type = SupplyRelationTypeEnum.merchant;
                }
                goodsVO.setRelationType(type);
            });
        }
        return result;
    }

    /**
     * 查询启用的 供应商品  (按商品id 或 商品规格id)
     *
     * @param merchantId
     * @param goodsIdSet
     * @param modelIdSet
     * @return
     */
    private List<SupplierGoods> findEnableListBySupply(String merchantId, Set<String> goodsIdSet, Set<String> modelIdSet) {
        boolean goodsIdFlag = CollUtil.isNotEmpty(goodsIdSet);
        boolean modelIdFlag = CollUtil.isNotEmpty(modelIdSet);
        if (!goodsIdFlag && !modelIdFlag) {
            return new ArrayList<>(8);
        }
        return supplierGoodsService.list(Wrappers.<SupplierGoods>query().lambda()
                .eq(SupplierGoods::getSupplierMerchantId, merchantId)
                .eq(SupplierGoods::getStatus, UseStatusEnum.enabled)
                .and(q -> q.in(goodsIdFlag, SupplierGoods::getSupplyGoodsId, goodsIdSet)
                        .or()
                        .in(modelIdFlag, SupplierGoods::getSupplyModelId, modelIdSet)
                )
        );
    }

    @Override
    public SupplyGoodsInfoVO fetchInfo(SupplyGoodsReq req) {
        SupplierMerchantInfoVO merchantShop = checkSupplier(req.getSupplierId(), req.getShopId());
        GoodsFeignReq feignReq = new GoodsFeignReq();
        feignReq.setGoodsId(req.getGoodsId());
        GoodsVO goods = scmSupplyUtils.fetchGoodsInfoById(feignReq);
        if (!StrUtil.equals(goods.getShopId(), req.getShopId())) {
            throw new ErrorDataException("商品有误, 不属于供应店铺商品");
        }
        SupplyGoodsInfoVO result = new SupplyGoodsInfoVO(goods);
        SupplyRelationTypeEnum type = SupplyRelationTypeEnum.no;
        // 关联商品规格处理
        int size = Math.max(16, goods.getModelList().size() * 4 / 3 + 1);
        Map<String, SupplyModelVO> modelMap = new HashMap<>(size);
        result.setModelList(goods.getModelList().stream()
                .map(item -> {
                    SupplyModelVO modelVO = new SupplyModelVO(item);
                    modelMap.put(modelVO.getModelId(), modelVO);
                    return modelVO;
                }).collect(Collectors.toList())
        );
        Set<String> goodsIdSet = new HashSet<>(4);
        goodsIdSet.add(goods.getGoodsId());
        List<SupplierGoods> list = findEnableListBySupply(merchantShop.getMerchantId(), goodsIdSet, modelMap.keySet());
        // 关联到 商家或 供应人
        if (CollUtil.isNotEmpty(list)) {
            type = modelHandle(list, modelMap);
        }
        result.setRelationType(type);
        return result;
    }

    /**
     * 关联商品规格处理 关联类型
     *
     * @param list
     * @param modelMap
     * @return
     */
    private SupplyRelationTypeEnum modelHandle(List<SupplierGoods> list, Map<String, SupplyModelVO> modelMap) {
        SupplyRelationTypeEnum type = SupplyRelationTypeEnum.merchant;
        // 是否存在关联到供应人
        AtomicBoolean flag = new AtomicBoolean(false);
        list.forEach(item -> {
            SupplyModelVO modelVO = modelMap.get(item.getSupplyModelId());
            if (null != modelVO) {
                boolean supplierFlag = StrUtil.isEmpty(item.getSupplierId());
                modelVO.setRelationType(supplierFlag ? SupplyRelationTypeEnum.merchant : SupplyRelationTypeEnum.supplier);
                if (!supplierFlag && !flag.get()) {
                    flag.set(true);
                }
            }
        });
        if (flag.get()) {
            type = SupplyRelationTypeEnum.supplier;
        }
        return type;
    }

    /**
     * 新增关联供应商品规格到平台
     * @param req
     * @return
     */
    @Override
    public boolean relationGoodsModel(SupplyGoodsEditReq req) {
        SupplierMerchantInfoVO merchantShop = checkSupplier(req.getSupplierId(), req.getShopId());
        // 是否已有关联
        SupplierGoods supplierGoods = supplierGoodsService.fetchOneByModel(merchantShop.getMerchantId(), req.getSupplyModelId(), req.getPlatformModelId());
        if (null != supplierGoods) {
            SupplierGoods update = new SupplierGoods();
            update.setId(supplierGoods.getId());
            update.setStatus(UseStatusEnum.enabled);
            return supplierGoodsService.updateById(update);
        }
        // 商品规格查询
        Merchant platformMerchant = scmSupplyUtils.fetchPlatformMerchant();
        GoodsModelFeignReq feignReq = new GoodsModelFeignReq();
        feignReq.setMerchantId(platformMerchant.getId());
        feignReq.setModelId(req.getPlatformModelId());
        GoodsModelDTO platformModel = scmSupplyUtils.fetchGoodsModelDTO(feignReq);
        if (null == platformModel) {
            throw new ErrorDataException("平台商品规格有误");
        }
        // 供应商品
        feignReq.setMerchantId(null);
        feignReq.setShopId(req.getShopId());
        feignReq.setModelId(req.getSupplyModelId());
        GoodsModelDTO supplyModel = scmSupplyUtils.fetchGoodsModelDTO(feignReq);
        if (null == supplyModel) {
            throw new ErrorDataException("供应商品规格有误");
        }
        if (supplyModel.getIsMarketable() != 1) {
            throw new ErrorDataException("供应商品未上架");
        }
        // 关联新增
        SupplierGoods relation = SupplyGoodsTrans.initRelation(merchantShop.getMerchantId(), platformModel, supplyModel);
        return supplierGoodsService.save(relation);
    }

    @Override
    public boolean removeRelationGoods(SupplyGoodsEditReq req) {
        SupplierMerchantInfoVO merchantShop = checkSupplier(req.getSupplierId(), req.getShopId());
        // 是否已有关联
        List<String> idList = supplierGoodsService.list(Wrappers.<SupplierGoods>query().lambda()
                .eq(SupplierGoods::getSupplierMerchantId, merchantShop.getMerchantId())
                .eq(SupplierGoods::getSupplyModelId, req.getSupplyModelId())
                .eq(StrUtil.isNotEmpty(req.getPlatformModelId()), SupplierGoods::getGoodsModelId, req.getPlatformModelId())
                .eq(SupplierGoods::getStatus, UseStatusEnum.enabled)
        ).stream().map(SupplierGoods::getId).collect(Collectors.toList());
        if (idList.isEmpty()) {
            throw new ErrorDataException("找不到关联商品");
        }
        SupplierGoods update = new SupplierGoods();
        update.setStatus(UseStatusEnum.disabled);
        return supplierGoodsService.update(update, Wrappers.<SupplierGoods>query().lambda()
                .in(SupplierGoods::getId, idList)
        );
    }

    /**
     * 供应商品新增到平台售卖
     *
     * @param req
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean platformSales(SupplyGoodsPlatformSalesReq req) {
        Shop shop = scmSupplyUtils.fetchShopById(req.getShopId());
        // 是否已有关联
        int num = supplierGoodsService.count(Wrappers.<SupplierGoods>query().lambda()
                .eq(SupplierGoods::getSupplierMerchantId, shop.getMerchantId())
                .eq(SupplierGoods::getSupplyGoodsId, req.getSupplyGoodsId())
                .eq(SupplierGoods::getStatus, UseStatusEnum.enabled)
        );
        if (num > 0) {
            throw new ErrorDataException("该供应商品已在平台售卖");
        }
        // 根据供应商品创建平台商品
        List<SupplierGoods> relationList = scmSupplyUtils.createGoodsBySupplyGoods(req.getPlatformShopId(), req.getSupplyGoodsId());
        // 关联
        supplierGoodsService.remove(Wrappers.<SupplierGoods>query().lambda()
                .eq(SupplierGoods::getSupplierMerchantId, shop.getMerchantId())
                .eq(SupplierGoods::getSupplyGoodsId, req.getSupplyGoodsId())
        );
        relationList.forEach(item -> {
            item.setSupplierMerchantId(shop.getMerchantId());
            supplierGoodsService.save(item);
        });
        return true;
    }

    /**
     * 取消供应商品平台售卖
     *
     * @param req
     * @return
     */
    @Override
    public boolean removePlatformSales(SupplyGoodsPlatformSalesReq req) {
        Shop shop = scmSupplyUtils.fetchShopById(req.getShopId());
        // 是否已有关联
        int num = supplierGoodsService.count(Wrappers.<SupplierGoods>query().lambda()
                .eq(SupplierGoods::getSupplierMerchantId, shop.getMerchantId())
                .eq(SupplierGoods::getSupplyGoodsId, req.getSupplyGoodsId())
                .eq(SupplierGoods::getStatus, UseStatusEnum.enabled)
        );
        if (num == 0) {
            return true;
        }
        SupplierGoods update = new SupplierGoods();
        update.setStatus(UseStatusEnum.disabled);
        supplierGoodsService.update(update, Wrappers.<SupplierGoods>query().lambda()
                .eq(SupplierGoods::getSupplierMerchantId, shop.getMerchantId())
                .eq(SupplierGoods::getSupplyGoodsId, req.getSupplyGoodsId())
        );
        return true;
    }

    /**
     * 查询平台商品规格对应的供应商品信息
     *
     * @param goodsModelId
     * @return
     */
    @Override
    public PlatformRelationModelVO platformModelRelation(String goodsModelId) {
        // 关联平台规格的供应商品规格
        SupplySqlDTO query = new SupplySqlDTO();
        query.setModelId(goodsModelId);
        query.setStatus(UseStatusEnum.enabled);
        List<SupplyGoodsDTO> relationList = supplierGoodsService.findListWithExt(query);
        PlatformRelationModelVO result = new PlatformRelationModelVO(goodsModelId);
        if (relationList.isEmpty()) {
            result.setModelList(new ArrayList<>(0));
            return result;
        }
        // key:供应商品规格id
        Map<String, SupplyGoodsDTO> modelMap = relationList.stream()
                .collect(Collectors.toMap(SupplyGoodsDTO::getSupplyModelId, Function.identity(), (oldValue, newValue) -> newValue));

        // 供应商品规格
        GoodsModelFeignReq req = new GoodsModelFeignReq();
        req.setModelIdSet(modelMap.keySet());
        List<GoodsModelDTO> modelList = scmSupplyUtils.findGoodsModelList(req);
        result.setModelList(modelList.stream().map(model -> {
            SupplyModelExtVO modelVO = new SupplyModelExtVO(model);
            modelVO.setMerchantName(modelMap.get(model.getId()).getMerchantName());
            return modelVO;
        }).collect(Collectors.toList()));
        return result;
    }

    /**
     * 删除商品的供应关联关系
     *
     * @param goodsId
     * @return
     */
    @Override
    public boolean deleteRelationByGoods(String goodsId) {
        if (StrUtil.isEmpty(goodsId)) {
            return false;
        }
        return supplierGoodsService.remove(Wrappers.<SupplierGoods>query().lambda()
                .nested(q -> q.eq(SupplierGoods::getGoodsId, goodsId)
                        .or()
                        .eq(SupplierGoods::getSupplyGoodsId, goodsId)
                )
        );
    }
}
